package com.yk.i_wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yk.i_wms.common.model.CheckWarehouseEnum;
import com.yk.i_wms.common.model.LocationTypeEnum;
import com.yk.i_wms.common.model.Result;
import com.yk.i_wms.mapper.SmsStockInfoMapper;
import com.yk.i_wms.model.*;
import com.yk.i_wms.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 库存信息
 *
 * @author hbq
 * @date 2021-04-03 14:15:00
 */
@Slf4j
@Service
public class SmsStockInfoServiceImpl extends ServiceImpl<SmsStockInfoMapper, SmsStockInfo> implements ISmsStockInfoService {
    @Resource
    private SmsStockInfoMapper smsStockInfoMapper;
    @Autowired
    private IUmsItemService umsItemService;
    @Autowired
    private ISmsStockDelayLogService smsStockDelayLogService;
    @Autowired
    private ISmsStockBakeLogService smsStockBakeLogService;
    @Autowired
    private IUmsMsdRuleService umsMsdRuleService;
    @Autowired
    private ISmsStockOperationLogService smsStockOperationLogService;
    @Autowired
    private IUmsWarehouseLocationService umsWarehouseLocationService;
    /**
     * 列表
     * @param params
     * @return
     */
    public Page<Map> findList(Map<String, Object> params){
        Integer pageNum = MapUtils.getInteger(params, "pageNum");
        Integer pageSize = MapUtils.getInteger(params, "pageSize");
        if (pageNum == null) {
            pageNum = 1;
        }
        if (pageSize == null) {
            pageSize = -1;
        }
        Page<Map> pages = new Page<>(pageNum, pageSize);
        return smsStockInfoMapper.findList(pages, params);
    }

    @Override
    public Page<Map> findTotalList(Map<String, Object> params) {
        Integer pageNum = MapUtils.getInteger(params, "pageNum");
        Integer pageSize = MapUtils.getInteger(params, "pageSize");
        if (pageNum == null) {
            pageNum = 1;
        }
        if (pageSize == null) {
            pageSize = -1;
        }
        Page<Map> pages = new Page<>(pageNum, pageSize);
        return smsStockInfoMapper.findTotalList(pages, params);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result delay(Map<String, Object> params) {
        try{
            String sn = MapUtil.getStr(params, "sn");
            Integer delayDates = MapUtil.getInt(params, "delayDates");
            String createName = MapUtil.getStr(params, "createName");
            SmsStockInfo stockInfo = getOne(new LambdaQueryWrapper<SmsStockInfo>().eq(SmsStockInfo::getSn, sn));
            if (stockInfo == null) {
                return Result.failed("无此条码");
            }
            String itemCode = stockInfo.getItemCode();
            UmsItem item = umsItemService.getOne(new LambdaQueryWrapper<UmsItem>().eq(UmsItem::getItemCode, itemCode));
            if (item == null) {
                return Result.failed("无此物料");
            }
            if (delayDates>item.getValidUntil()){
                return Result.failed("延期时长大于有效期");
            }
            Date beforeChangeTime = stockInfo.getTimeoutDate();
            DateTime afterChangeTime = DateUtil.offsetDay(beforeChangeTime, delayDates);
            stockInfo.setTimeoutDate(afterChangeTime);
            saveOrUpdate(stockInfo);

            //添加延期日志
            SmsStockDelayLog smsStockDelayLog = new SmsStockDelayLog();
            smsStockDelayLog.setSn(sn);
            smsStockDelayLog.setBeforeChangeTime(beforeChangeTime);
            smsStockDelayLog.setAfterChangeTime(afterChangeTime);
            smsStockDelayLog.setDelayDates(delayDates);
            smsStockDelayLog.setCreateName(createName);
            smsStockDelayLogService.save(smsStockDelayLog);
            return Result.succeed("保存成功");
        }
        catch (Exception e){
            // 事务回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.failed( e,"保存失败,请联系管理员");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result bake(SmsStockBakeLog smsStockBakeLog) {
        try{
            String sn = smsStockBakeLog.getSn();
            SmsStockInfo stockInfo = getOne(new LambdaQueryWrapper<SmsStockInfo>().eq(SmsStockInfo::getSn, sn));
            if (stockInfo == null) {
                return Result.failed("无此条码");
            }
            String itemCode = stockInfo.getItemCode();
            UmsItem item = umsItemService.getOne(new LambdaQueryWrapper<UmsItem>().eq(UmsItem::getItemCode, itemCode));
            if (item == null) {
                return Result.failed("无此物料");
            }
            String msdCode = item.getMsdCode();
            UmsMsdRule msdRule = umsMsdRuleService.getOne(new LambdaQueryWrapper<UmsMsdRule>().eq(UmsMsdRule::getMsdCode, msdCode));
            if (msdRule == null) {
                return Result.failed("无此湿敏规则");
            }
            //更新烘烤次数
            stockInfo.setExposeTimes(Convert.toBigDecimal(0));
            stockInfo.setBakeTimes(stockInfo.getBakeTimes()+1);
            updateById(stockInfo);

            //添加烘烤记录
            smsStockBakeLogService.save(smsStockBakeLog);
            Long bakeTimes = stockInfo.getBakeTimes();
            if (bakeTimes>=msdRule.getMaxBakeTimes()){
                return Result.succeed("超过最大烘烤次数");
            }
            return Result.succeed("保存成功");
        }
        catch (Exception e){
            // 事务回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.failed( e,"保存失败,请联系管理员");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result putAway(Map<String, Object> params) {
        try{
            log.info("扫码上架请求参数{}",params);
            String sn = MapUtil.getStr(params, "sn");
            String areaSn = MapUtil.getStr(params, "areaSn");
            String createName = MapUtil.getStr(params, "createName");
            Integer operationType = MapUtil.getInt(params, "operationType");
            SmsStockOperationLog stockOperationLog = smsStockOperationLogService.getOne(new LambdaQueryWrapper<SmsStockOperationLog>()
                    .eq(SmsStockOperationLog::getSn, sn)
                    .eq(SmsStockOperationLog::getType, 1)
            );
            if (operationType == 1 && stockOperationLog != null) {
                return Result.failed("已存在IQC上架记录");
            }
            if (operationType == 2 && stockOperationLog == null) {
                return Result.failed("未存在IQC上架记录");
            }
            UmsWarehouseLocation location = umsWarehouseLocationService.getOne(new LambdaQueryWrapper<UmsWarehouseLocation>().eq(UmsWarehouseLocation::getAreaSn, areaSn));
            if (location == null) {
                return Result.failed("库位不存在");
            }
            SmsStockInfo stockInfo = getOne(new LambdaQueryWrapper<SmsStockInfo>().eq(SmsStockInfo::getSn, sn));
            if (stockInfo == null) {
                return Result.failed("无此条码");
            }
            if (stockInfo.getCheckState()== 2) {
                return Result.failed("sn未检验");
            }
            if (stockInfo.getCheckState()== 4) {
                return Result.failed("sn检验不合格");
            }
            if (StrUtil.isNotBlank(stockInfo.getAreaSn())) {
                return Result.failed("sn已上架");
            }
            List<SmsStockInfo> stockInfos = list(new LambdaQueryWrapper<SmsStockInfo>().eq(SmsStockInfo::getAreaSn, areaSn));
            if (!stockInfos.isEmpty()){
                return Result.failed("库位被占用");
            }
            UmsItem item = umsItemService.getOne(new LambdaQueryWrapper<UmsItem>().eq(UmsItem::getItemCode, stockInfo.getItemCode()));
            if (StrUtil.isNotBlank(item.getMsdCode())&&!LocationTypeEnum.MSD.getLtCode().equals(location.getLtCode())) {
                return Result.failed("湿敏物料需要放至湿敏货架上");
            }
            stockInfo.setWhCode(location.getWhCode());
            stockInfo.setAreaSn(areaSn);
            updateById(stockInfo);
            //添加操作日志
            SmsStockOperationLog smsStockOperationLog = new SmsStockOperationLog();
            smsStockOperationLog.setSn(sn);
            smsStockOperationLog.setDocNo(stockInfo.getDocNo());
            smsStockOperationLog.setType(operationType);
            smsStockOperationLog.setItemCode(stockInfo.getItemCode());
            smsStockOperationLog.setItemName(stockInfo.getItemName());
            smsStockOperationLog.setWarehouse(stockInfo.getWarehouse());
            smsStockOperationLog.setAreaSn(areaSn);
            smsStockOperationLog.setQty(stockInfo.getQty());
            smsStockOperationLog.setCreateName(createName);
            smsStockOperationLogService.save(smsStockOperationLog);
            return Result.succeed("保存成功");
        }
        catch (Exception e){
            // 事务回滚
            log.error("扫码上架异常：",e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.failed( e,"保存失败,请联系管理员");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result soldOut(Map<String, Object> params) {
        try{
            log.info("扫码入库请求参数{}",params);
            String sn = MapUtil.getStr(params, "sn");
            String createName = MapUtil.getStr(params, "createName");
            Integer operationType = MapUtil.getInt(params, "operationType");
            SmsStockOperationLog stockOperationLog = smsStockOperationLogService.getOne(new LambdaQueryWrapper<SmsStockOperationLog>()
                    .eq(SmsStockOperationLog::getSn, sn)
                    .eq(SmsStockOperationLog::getType, 1)
            );
            if (stockOperationLog == null) {
                return Result.failed("未存在上架记录");
            }
            SmsStockInfo stockInfo = getOne(new LambdaQueryWrapper<SmsStockInfo>().eq(SmsStockInfo::getSn, sn));
            if (stockInfo == null) {
                return Result.failed("无此条码");
            }
            if (!stockInfo.getWarehouse().equals(CheckWarehouseEnum.S_1.getWarehouse())){
                return Result.failed("条码不在良品库");
            }
            if (!StrUtil.isNotBlank(stockInfo.getAreaSn())) {
                return Result.failed("sn未上架");
            }
            //更新库存信息
            stockInfo.setAreaSn("");
            updateById(stockInfo);

            //添加操作日志
            SmsStockOperationLog smsStockOperationLog = new SmsStockOperationLog();
            smsStockOperationLog.setSn(sn);
            smsStockOperationLog.setDocNo(stockInfo.getDocNo());
            smsStockOperationLog.setType(operationType);
            smsStockOperationLog.setItemCode(stockInfo.getItemCode());
            smsStockOperationLog.setItemName(stockInfo.getItemName());
            smsStockOperationLog.setWarehouse(stockInfo.getWarehouse());
            smsStockOperationLog.setAreaSn("");
            smsStockOperationLog.setQty(stockInfo.getQty());
            smsStockOperationLog.setCreateName(createName);
            smsStockOperationLogService.save(smsStockOperationLog);
            return Result.succeed("保存成功");
        }
        catch (Exception e){
            // 事务回滚
            log.error("扫码下架异常：",e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.failed( e,"保存失败,请联系管理员");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result change(Map<String, Object> params) {
        try{
            log.info("扫码换库请求参数{}",params);
            String sn = MapUtil.getStr(params, "sn");
            String areaSn = MapUtil.getStr(params, "areaSn");
            String createName = MapUtil.getStr(params, "createName");
            Integer operationType = MapUtil.getInt(params, "operationType");
            UmsWarehouseLocation location = umsWarehouseLocationService.getOne(new LambdaQueryWrapper<UmsWarehouseLocation>().eq(UmsWarehouseLocation::getAreaSn, areaSn));
            if (location == null) {
                return Result.failed("库位不存在");
            }
            SmsStockInfo stockInfo = getOne(new LambdaQueryWrapper<SmsStockInfo>().eq(SmsStockInfo::getSn, sn));
            if (stockInfo == null) {
                return Result.failed("无此条码");
            }
            if (!StrUtil.isNotBlank(stockInfo.getAreaSn())) {
                return Result.failed("sn未上架");
            }
            List<SmsStockInfo> stockInfos = list(new LambdaQueryWrapper<SmsStockInfo>().eq(SmsStockInfo::getAreaSn, areaSn));
            if (!stockInfos.isEmpty()){
                return Result.failed("库位被占用");
            }
            UmsItem item = umsItemService.getOne(new LambdaQueryWrapper<UmsItem>().eq(UmsItem::getItemCode, stockInfo.getItemCode()));
            if (StrUtil.isNotBlank(item.getMsdCode())&&!LocationTypeEnum.MSD.getLtCode().equals(location.getLtCode())){
                return Result.failed("湿敏物料需要放至湿敏货架上");
            }
            stockInfo.setAreaSn(areaSn);
            updateById(stockInfo);
            //添加操作日志
            SmsStockOperationLog smsStockOperationLog = new SmsStockOperationLog();
            smsStockOperationLog.setSn(sn);
            smsStockOperationLog.setDocNo(stockInfo.getDocNo());
            smsStockOperationLog.setType(operationType);
            smsStockOperationLog.setItemCode(stockInfo.getItemCode());
            smsStockOperationLog.setItemName(stockInfo.getItemName());
            smsStockOperationLog.setWarehouse(stockInfo.getWarehouse());
            smsStockOperationLog.setAreaSn(areaSn);
            smsStockOperationLog.setQty(stockInfo.getQty());
            smsStockOperationLog.setCreateName(createName);
            smsStockOperationLogService.save(smsStockOperationLog);
            return Result.succeed("保存成功");
        }
        catch (Exception e){
            // 事务回滚
            log.error("扫码换库异常：",e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.failed( e,"保存失败,请联系管理员");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result spilt(Map<String, Object> params) {
        try{
            log.info("扫码拆签请求参数{}",params);
            String sn = MapUtil.getStr(params, "sn");
            Long amount = MapUtil.getLong(params, "amount");
            Integer operationType = MapUtil.getInt(params, "operationType");
            String createName = MapUtil.getStr(params, "createName");
            if (amount<=0){
                return Result.failed("输入数量有误");
            }
            //从最后一个|后截取-
            String[] split = sn.split("\\|");
            String suffix = split[split.length - 1];
            String prefix = StrUtil.removeSuffix(sn, suffix)+StrUtil.sub(suffix,0,4)+"-";
            SmsStockInfo stockInfo = getOne(new LambdaQueryWrapper<SmsStockInfo>().eq(SmsStockInfo::getSn, sn));
            if (stockInfo == null) {
                return Result.failed("无此条码");
            }
            if (StrUtil.isNotBlank(stockInfo.getAreaSn())){
                return Result.failed("请先下架");
            }
            Long existAmount = stockInfo.getQty();
            if (existAmount<=1||existAmount<amount){
                return Result.failed("拆分数量不符");
            }
            String newTblBarcode=prefix+"1";
            SmsStockInfo one = getOne(new QueryWrapper<SmsStockInfo>()
                    .last("where sn like '" + prefix + "%' order by sn desc limit 1"));
            if (one != null) {
                Long aLong = Convert.toLong(StrUtil.removePrefix(one.getSn(), prefix));
                newTblBarcode=prefix+(aLong+1);
            }
            //1. 添加克隆条码库存信息
            SmsStockInfo newStockInfo=new SmsStockInfo();
            BeanUtil.copyProperties(stockInfo,newStockInfo);
            newStockInfo.setQty(amount);
            newStockInfo.setSn(newTblBarcode);
            newStockInfo.setIsOpen(1);
            newStockInfo.setHasPrint(0);
            save(newStockInfo);

            //2. 修改原库存数量
            stockInfo.setQty(existAmount-amount);
            stockInfo.setIsOpen(1);
            stockInfo.setHasPrint(0);
            updateById(stockInfo);

            //3. 添加操作日志
            SmsStockOperationLog smsStockOperationLog = new SmsStockOperationLog();
            smsStockOperationLog.setSn(sn);
            smsStockOperationLog.setDocNo(stockInfo.getDocNo());
            smsStockOperationLog.setType(operationType);
            smsStockOperationLog.setItemCode(stockInfo.getItemCode());
            smsStockOperationLog.setItemName(stockInfo.getItemName());
            smsStockOperationLog.setWarehouse(stockInfo.getWarehouse());
            smsStockOperationLog.setAreaSn("");
            smsStockOperationLog.setQty(stockInfo.getQty());
            smsStockOperationLog.setCreateName(createName);
            smsStockOperationLog.setRemark("条码:'"+sn+"'拆分出条码:'"+newTblBarcode+"',新条码数量为"+amount);
            smsStockOperationLogService.save(smsStockOperationLog);
            return Result.succeed("保存成功，新条码："+newTblBarcode);
        }
        catch (Exception e){
            // 事务回滚
            log.error("扫码拆签异常：",e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.failed( e,"保存失败,请联系管理员");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result combine(Map<String, Object> params) {
        try{
            log.info("扫码合签请求参数{}",params);
            String fromSn = MapUtil.getStr(params, "fromSn"); //被合并的标签（删除）
            String toSn = MapUtil.getStr(params, "toSn");   //合并到的标签（数量增加）
            Integer operationType = MapUtil.getInt(params, "operationType");
            String createName = MapUtil.getStr(params, "createName");
            String[] fromSplit = fromSn.split("\\|");
            String fromSuffix = fromSplit[fromSplit.length - 1];
            String fromPrefix = StrUtil.removeSuffix(fromSn, fromSuffix)+StrUtil.sub(fromSuffix,0,4);

            String[] toSplit = toSn.split("\\|");
            String toSuffix = toSplit[toSplit.length - 1];
            String toPrefix = StrUtil.removeSuffix(toSn, toSuffix)+StrUtil.sub(toSuffix,0,4);
            /* 2021.05.17去除
            log.info(fromPrefix+"   "+toPrefix);
            if (!fromPrefix.equals(toPrefix)){
                return Result.failed("所合并条码信息不符");
            }*/
            SmsStockInfo fromStockInfo = getOne(new LambdaQueryWrapper<SmsStockInfo>()
                    .eq(SmsStockInfo::getSn, fromSn)
            );
            SmsStockInfo toStockInfo = getOne(new LambdaQueryWrapper<SmsStockInfo>()
                    .eq(SmsStockInfo::getSn, toSn)
            );
            if (fromStockInfo==null||toStockInfo==null){
                return Result.failed("条码不存在");
            }
            if (StrUtil.isNotBlank(fromStockInfo.getAreaSn())||StrUtil.isNotBlank(toStockInfo.getAreaSn())){
                return Result.failed("请先下架");
            }
            if (!fromStockInfo.getStockState().equals(toStockInfo.getStockState())){
                return Result.failed("条码状态不同");
            }
            if (!fromStockInfo.getWarehouse().equals(toStockInfo.getWarehouse())){
                return Result.failed("合并条码非同库区");
            }
            if (!fromStockInfo.getBatch().equals(toStockInfo.getBatch())){
                return Result.failed("只有相同批次可以合并");
            }
            if (!fromStockInfo.getItemCode().equals(toStockInfo.getItemCode())){
                return Result.failed("只有同物料可以进行合并");
            }
            //1.修改条码数量
            Long amount = fromStockInfo.getQty();
            toStockInfo.setQty(toStockInfo.getQty()+amount);
            toStockInfo.setIsOpen(1);
            toStockInfo.setHasPrint(0);
            updateById(toStockInfo);
            //2.删除被合并条码
            removeById(fromStockInfo);
            //3. 添加操作日志
            SmsStockOperationLog smsStockOperationLog = new SmsStockOperationLog();
            smsStockOperationLog.setSn(toSn);
            smsStockOperationLog.setDocNo(toStockInfo.getDocNo());
            smsStockOperationLog.setType(operationType);
            smsStockOperationLog.setItemCode(toStockInfo.getItemCode());
            smsStockOperationLog.setItemName(toStockInfo.getItemName());
            smsStockOperationLog.setWarehouse(toStockInfo.getWarehouse());
            smsStockOperationLog.setAreaSn("");
            smsStockOperationLog.setQty(toStockInfo.getQty());
            smsStockOperationLog.setCreateName(createName);
            smsStockOperationLog.setRemark("条码:'"+fromSn+"' 合并至条码:'"+toSn+"',数量增加了"+amount);
            smsStockOperationLogService.save(smsStockOperationLog);
            return Result.succeed("保存成功");
        }
        catch (Exception e){
            // 事务回滚
            log.error("扫码合签异常：",e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.failed( e,"保存失败,请联系管理员");
        }
    }

}
